package com.fast.orm.data;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class Where<T, P> extends BaseMapper<P> {
    private final T fields;

    public Where(DataPackage dataPackage, T fields) {
        this.dataPackage = dataPackage;
        this.fields = fields;
    }

    /**
     * @param value 值等于条件,如果参数为数组并且长度大于1,使用in查询
     * @return 条件操作工具
     */
    public T eqTo(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.Equal));
        return fields;
    }

    public T eqTo(BaseMapper<?> baseMapper) {
        if (baseMapper == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), baseMapper, dataPackage.getWay(), Expression.Equal));
        return fields;
    }

    /**
     * @param value 值等不于条件,如果参数为数组并且长度大于1,使用not in查询
     * @return 条件操作工具
     */
    public T notEqTo(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.NotEqual));
        return fields;
    }

    public T notEqTo(BaseMapper<?> baseMapper) {
        if (baseMapper == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), baseMapper, dataPackage.getWay(), Expression.NotEqual));
        return fields;
    }

    /**
     * 值模糊查询条件
     *
     * @param value 值
     * @return 条件操作工具
     */
    public T like(String value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), "%" + value + "%", dataPackage.getWay(), Expression.Like));
        return fields;
    }


    /**
     * 值模糊查询条件
     *
     * @param value 值
     * @return 条件操作工具
     */
    public T notLike(String value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), "%" + value + "%", dataPackage.getWay(), Expression.NotLike));
        return fields;
    }

    /**
     * 值模糊查询条件
     *
     * @param value 值
     * @return 条件操作工具
     */
    public T likeLeft(String value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), "%" + value, dataPackage.getWay(), Expression.Like));
        return fields;
    }

    /**
     * 值模糊查询条件
     *
     * @param value 值
     * @return 条件操作工具
     */
    public T notLikeLeft(String value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), "%" + value, dataPackage.getWay(), Expression.NotLike));
        return fields;
    }

    /**
     * 值模糊查询条件
     *
     * @param value 值
     * @return 条件操作工具
     */
    public T likeRight(String value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value + "%", dataPackage.getWay(), Expression.Like));
        return fields;
    }

    /**
     * 值模糊查询条件
     *
     * @param value 值
     * @return 条件操作工具
     */
    public T notLikeRight(String value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value + "%", dataPackage.getWay(), Expression.NotLike));
        return fields;
    }

    /**
     * 全文检索条件
     *
     * @param value 全文检索条件
     * @return 条件操作工具
     */
    public T match(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.Match));
        return fields;
    }

    /**
     * 全文检索条件 Not
     *
     * @param value 全文检索条件
     * @return 条件操作工具
     */
    public T notMatch(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.NotMatch));
        return fields;
    }


    /**
     * 包含条件
     *
     * @param values 所包含的值(a,b,c)
     * @return 条件操作工具
     */
    public T in(Comparable<?>... values) {
        if (ArrayUtil.isEmpty(values)) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), new ArrayList<>(Arrays.asList(values)), dataPackage.getWay(), Expression.In));
        return fields;
    }

    /**
     * 不包含条件
     *
     * @param values 所包含的值(a,b,c)
     * @return 条件操作工具
     */
    public T notIn(Comparable<?>... values) {
        if (ArrayUtil.isEmpty(values)) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), new ArrayList<>(Arrays.asList(values)), dataPackage.getWay(), Expression.NotIn));
        return fields;
    }

    /**
     * 包含查询
     *
     * @param values 所包含的值([a,b,c])
     * @return 条件操作工具
     */
    public T in(Collection<?> values) {
        if (CollUtil.isEmpty(values)) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), values, dataPackage.getWay(), Expression.In));
        return fields;
    }

    /**
     * 不包含查询
     *
     * @param values 所包含的值([a,b,c])
     * @return 条件操作工具
     */
    public T notIn(Collection<Comparable<?>> values) {
        if (CollUtil.isEmpty(values)) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), values, dataPackage.getWay(), Expression.NotIn));
        return fields;
    }

    /**
     * 范围条件
     *
     * @param betweenMin 最小值
     * @param betweenMax 最大值
     * @return 条件操作工具
     */
    public T between(Comparable<?> betweenMin, Comparable<?> betweenMax) {
        if (betweenMin == null || betweenMax == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), betweenMin, betweenMax, dataPackage.getWay(), Expression.Between));
        return fields;
    }

    /**
     * 排除范围条件
     *
     * @param betweenMin 最小值
     * @param betweenMax 最大值
     * @return 条件操作工具
     */
    public T notBetween(Comparable<?> betweenMin, Comparable<?> betweenMax) {
        if (betweenMin == null || betweenMax == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), betweenMin, betweenMax, dataPackage.getWay(), Expression.NotBetween));
        return fields;
    }

    /**
     * 值不为空条件
     *
     * @return 条件操作工具
     */
    public T notNull() {
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), dataPackage.getWay(), Expression.NotNull));
        return fields;
    }

    /**
     * 值为空条件
     *
     * @return 条件操作工具
     */
    public T isNull() {
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), dataPackage.getWay(), Expression.Null));
        return fields;
    }

    /**
     * 值大于等于条件
     *
     * @param value 值等于条件
     * @return 条件操作工具
     */
    public T greaterOrEqual(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.GreaterOrEqual));
        return fields;
    }

    public T greaterOrEqual(BaseMapper<?> baseMapper) {
        if (baseMapper == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), baseMapper, dataPackage.getWay(), Expression.GreaterOrEqual));
        return fields;
    }

    /**
     * 值小于等于条件
     *
     * @param value 值等于条件
     * @return 条件操作工具
     */
    public T lessOrEqual(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.LessOrEqual));
        return fields;
    }

    public T lessOrEqual(BaseMapper<?> baseMapper) {
        if (baseMapper == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), baseMapper, dataPackage.getWay(), Expression.LessOrEqual));
        return fields;
    }

    /**
     * 值大于条件
     *
     * @param value 值等于条件
     * @return 条件操作工具
     */
    public T greater(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.Greater));
        return fields;
    }

    public T greater(BaseMapper<?> baseMapper) {
        if (baseMapper == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), baseMapper, dataPackage.getWay(), Expression.Greater));
        return fields;
    }

    /**
     * 值小于条件
     *
     * @param value 值等于条件
     * @return 条件操作工具
     */
    public T less(Comparable<?> value) {
        if (value == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, dataPackage.getWay(), Expression.Less));
        return fields;
    }

    public T less(BaseMapper<?> baseMapper) {
        if (baseMapper == null) {
            return fields;
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), baseMapper, dataPackage.getWay(), Expression.Less));
        return fields;
    }


    public T findInSet(Comparable<?>... values) {
        if (ArrayUtil.isEmpty(values)) {
            return fields;
        }
        if (values.length > 1) {
            ConditionSetting.setBracket(dataPackage, Expression.LeftBracket, dataPackage.getWay());
            for (Object value : values) {
                dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, DataPackage.Way.OR, Expression.FindInSet));
            }
            ConditionSetting.setBracket(dataPackage, Expression.RightBracket, DataPackage.Way.CUSTOM);
        } else {
            dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), values[0], dataPackage.getWay(), Expression.FindInSet));
        }
        return fields;
    }

    public T notFindInSet(Comparable<?>... values) {
        if (ArrayUtil.isEmpty(values)) {
            return fields;
        }
        if (values.length > 1) {
            ConditionSetting.setBracket(dataPackage, Expression.LeftBracket, dataPackage.getWay());
            for (Object value : values) {
                dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, DataPackage.Way.OR, Expression.NotFindInSet));
            }
            ConditionSetting.setBracket(dataPackage, Expression.RightBracket, DataPackage.Way.CUSTOM);
        } else {
            dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), values[0], dataPackage.getWay(), Expression.NotFindInSet));
        }
        return fields;
    }

    public T findInSet(List<Comparable<?>> values) {
        if (CollUtil.isEmpty(values)) {
            return fields;
        }
        if (values.size() > 1) {
            ConditionSetting.setBracket(dataPackage, Expression.LeftBracket, dataPackage.getWay());
            for (Object value : values) {
                dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, DataPackage.Way.OR, Expression.FindInSet));
            }
            ConditionSetting.setBracket(dataPackage, Expression.RightBracket, DataPackage.Way.CUSTOM);
        } else {
            dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), values.get(0), dataPackage.getWay(), Expression.FindInSet));
        }
        return fields;
    }

    public T notFindInSet(List<Comparable<?>> values) {
        if (CollUtil.isEmpty(values)) {
            return fields;
        }
        if (values.size() > 1) {
            ConditionSetting.setBracket(dataPackage, Expression.LeftBracket, dataPackage.getWay());
            for (Object value : values) {
                dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), value, DataPackage.Way.OR, Expression.NotFindInSet));
            }
            ConditionSetting.setBracket(dataPackage, Expression.RightBracket, DataPackage.Way.CUSTOM);
        } else {
            dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getField(), values.get(0), dataPackage.getWay(), Expression.NotFindInSet));
        }
        return fields;
    }

    /**
     * 对后续第一个条件使用OR封装
     *
     * @return 条件操作工具
     */
    public Where<T, P> or() {
        dataPackage.setWay(DataPackage.Way.OR);
        return this;
    }


}
